using System;
using UnityEngine;

public enum LevelStatus
{
    MainMenu,
    Normal, 
    Pool, 
    Fail,
    Pause
}

public class LevelManager : MonoSingleton<LevelManager>
{

    [Header("Level Data")]
    public LevelStatus status = LevelStatus.MainMenu;
    public float speedByBubbleSize = 2f;
    public float speedByEvents;
    public float levelSpeed {
        get {
            if (status == LevelStatus.Normal) return speedByBubbleSize + speedByEvents;
            if (status == LevelStatus.Fail) return 0;
            if (status == LevelStatus.MainMenu) return 2;
            if (status == LevelStatus.Pool) return 0;
            if (status == LevelStatus.Pause) return 0;
            return 2;
        }
    }
    [Header("Level Statistics")]
    public int m_CargoDilivered;
    public float m_TimePassed;
    public float m_DistancePassed;
    public float m_SectionPassedTotal;
    public float m_SectionPassedCurrent;
    [Header("Level Spawn")]
    public GameObject poolSectionPrefab;
    public Transform spawnRoot;
    public ThemeConfig currTheme;
    public int sectionSpawnIndex;
    public float sectionSpawnOffset = 0;
    public float sectionSpawnDistance = 19.2f;

    public event Action OnGameBegin;
    public event Action OnLevelPassed;
    public event Action OnSectionPassed;
    public event Action OnGameFail;

    public void GameBegin ()
    {
        sectionSpawnIndex = 0;
        m_SectionPassedTotal = 0;
        m_SectionPassedCurrent = 0;
        OnGameBegin?.Invoke();
        status=LevelStatus.Normal;
    }

    public void BackToMainMenu ()
    {
        Bubble.I.ResetBubble();
        Bubble.I.transform.position = new Vector3(-5, 0, -5);
    }

    /// <summary>
    /// Called when the bubble pass the section test line.
    /// </summary>
    public void PassSection ()
    {
        m_SectionPassedCurrent++;
        m_SectionPassedTotal++;
        OnSectionPassed?.Invoke();
    }

    /// <summary>
    /// Called when the bubble pass the pool test line.
    /// </summary>
    public void PassLevel ()
    {
        m_CargoDilivered++;
        m_SectionPassedCurrent = 0;
        status = LevelStatus.Pool;
        OnLevelPassed.Invoke();
    }

    /// <summary>
    /// Called when the bubble ends the pool animation.
    /// </summary>
    public void ContinueLevel ()
    {
        status = LevelStatus.Normal;
    }

    /// <summary>
    /// Called when the bubble
    /// </summary>
    public void GameFail ()
    {
        GameManager.I.PlaySound(AudioLib.I.s_Fail);
        Bubble.Instance.cargo.SetFalling();
        status = LevelStatus.Fail;
        OnGameFail?.Invoke();
    }

    public void SetStatus(LevelStatus status)
    {
        this.status = status;
    }

    private LevelStatus _prevStatus;
    public void PauseLevel()
    {
        _prevStatus = status;
        status = LevelStatus.Pause;
    }

    public void ResumeLevel()
    {
        status = _prevStatus;
    }

    protected override void Awake()
    {
        base.Awake();
        GameManager.I.currLevel = this;
        currTheme = GameManager.I.mainMenuTheme;
    }

    private void Update()
    {
        sectionSpawnOffset -= levelSpeed * Time.deltaTime;
        if (sectionSpawnOffset < 0) SpawnNewSection();
    }

    public void SpawnNewSection ()
    {
        sectionSpawnOffset += sectionSpawnDistance;
        if (status == LevelStatus.MainMenu)
        {
            SpawnSection(currTheme.GetRandomSection());
            return;
        }
        if (status == LevelStatus.Normal)
        {
            if (sectionSpawnIndex == 0)
            {
                SpawnSection(poolSectionPrefab);
                currTheme = GameManager.I.GetRandomTheme();
            }
            else
            {
                SpawnSection(currTheme.GetRandomSection());
            }
            sectionSpawnIndex = (sectionSpawnIndex + 1) % 15;
            return;
        }
    }

    public void SpawnSection (GameObject sectionPrefab)
    {
        Instantiate(sectionPrefab, 
            new Vector3(sectionSpawnOffset, 0, sectionPrefab.transform.position.z),
            Quaternion.identity, spawnRoot);
    }
}

